#pragma once

#include <memory>

#include "antlr4-runtime.h"

#include "complexCalculatorBaseVisitor.h"
#include "Symbol.h"
#include "backend.h"

class Visitor: public complexCalculatorBaseVisitor {
    public:
        antlrcpp::Any visitUnit(complexCalculatorParser::UnitContext *ctx) override;
        antlrcpp::Any visitDefUnit(complexCalculatorParser::DefUnitContext *ctx) override;
        antlrcpp::Any visitVarUnit(complexCalculatorParser::VarUnitContext *ctx) override;
        antlrcpp::Any visitType(complexCalculatorParser::TypeContext *ctx) override;
        antlrcpp::Any visitVarDef(complexCalculatorParser::VarDefContext *ctx) override;
        antlrcpp::Any visitInitVal(complexCalculatorParser::InitValContext *ctx) override;
        antlrcpp::Any visitExpNumber(complexCalculatorParser::ExpNumberContext *ctx) override;
        antlrcpp::Any visitExpAddSub(complexCalculatorParser::ExpAddSubContext *ctx) override;
        antlrcpp::Any visitNumber(complexCalculatorParser::NumberContext *ctx) override;

        antlrcpp::Any visitStatAssign(complexCalculatorParser::StatAssignContext *ctx) override;
        antlrcpp::Any visitStatExp(complexCalculatorParser::StatExpContext *ctx) override;
        antlrcpp::Any visitLVal(complexCalculatorParser::LValContext *ctx) override;

        antlrcpp::Any visitIdentifier(complexCalculatorParser::IdentifierContext *ctx) override;
        // antlrcpp::Any visitExpMulDiv(complexCalculatorParser::ExpMulDivContext *context) override;

        void setValue(antlr4::tree::ParseTree *node, std::shared_ptr<BaseSymbol> value);
        std::shared_ptr<BaseSymbol> getValue(antlr4::tree::ParseTree *node);

        void emit();
        
    private:
        antlr4::tree::ParseTreeProperty<std::shared_ptr<BaseSymbol>> valueTree;
        SymbolTable table;
        Backend backend;
};
